﻿#region 참조 네임스페이스

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;

#endregion

namespace Skying.IO
{
	public sealed class MJpegWriter : IDisposable
	{
		#region 상수

		/// <summary>
		/// 
		/// </summary>
		private const string _DEFAULT_BOUNDARY = "--boundary";

		/// <summary>
		/// 헤더 상수를 나타낸다.
		/// </summary>
		private const string _HEADER = "HTTP/1.1 200 OK{0}Content-Type: multipart/x-mixed-replace; boundary={1}{0}";

		/// <summary>
		/// 
		/// </summary>
		private const string _CONTENT_TYPE = "Content-Type: image/jpeg";

		/// <summary>
		/// 
		/// </summary>
		private const string _CONTENT_LENGTH = "Content-Length: {0}";

		#endregion

		#region 변수

		/// <summary>
		/// 
		/// </summary>
		private Encoding _encoding;

		#endregion

		#region 프로퍼티

		/// <summary>
		/// 
		/// </summary>
		public string Boundary
		{
			get;
			private set;
		}

		public Stream BaseStream
		{
			get;
			private set;
		}

		#endregion

		#region 생성자/소멸자

		public MJpegWriter(Stream stream)
			: this(stream, Encoding.ASCII)
		{

		}

		public MJpegWriter(Stream stream, Encoding encoding)
			: this(stream, _DEFAULT_BOUNDARY, encoding)
		{

		}

		public MJpegWriter(Stream stream, string boundary, Encoding encoding)
		{
			this.BaseStream = stream;

			this.Boundary = boundary;

			this._encoding = encoding;
		}

		#endregion

		#region 스트림 쓰기

		/// <summary>
		/// 스트림에 <see cref="System.Byte"/>의 배열을 쓴다.
		/// </summary>
		/// <param name="data">스트림에 쓸 <see cref="System.Byte"/>의 배열을 설정한다.</param>
		public void Write(byte[] data)
		{
			this.BaseStream.Write(data, 0, data.Length);
		}

		/// <summary>
		/// 스트림에 <see cref="System.String"/>을 쓴다.
		/// </summary>
		/// <param name="text"></param>
		public void Write(string text)
		{
			this.Write(this._encoding.GetBytes(text));
		}

		/// <summary>
		/// 스트림에 헤더를 쓴다.
		/// </summary>
		public void WriteHeader()
		{
			this.Write(string.Format(_HEADER, Environment.NewLine, this.Boundary));

			this.BaseStream.Flush();
		}

		/// <summary>
		/// 스트림에 <see cref="System.Drawing.Image"/>를 쓴다.
		/// </summary>
		/// <param name="image">스트림에 쓸 이미지를 설정한다.</param>
		public void Write(Image image)
		{
			MemoryStream imageStream = new MemoryStream();

			image.Save(imageStream, ImageFormat.Jpeg);

			this.Write(imageStream);
		}

		/// <summary>
		/// 스트림에 <see cref="System.IO.MemoryStream"/> 개체를 쓴다.
		/// </summary>
		/// <param name="imageStream">스트림에 쓸 <see cref="System.IO.MemoryStream"/> 개체를 쓴다.</param>
		public void Write(MemoryStream imageStream)
		{
			StringBuilder headerStrings = new StringBuilder();

			headerStrings.AppendLine();
			headerStrings.AppendLine(this.Boundary);
			headerStrings.AppendLine(_CONTENT_TYPE);
			headerStrings.AppendLine(string.Format(_CONTENT_LENGTH, imageStream.Length));
			headerStrings.AppendLine();

			this.Write(headerStrings.ToString());

			imageStream.WriteTo(this.BaseStream);

			this.Write(Environment.NewLine);

			this.BaseStream.Flush();
		}

		#endregion

		#region IDisposable 인터페이스 구현

		/// <summary>
		/// 
		/// </summary>
		public void Dispose()
		{
			try
			{
				if (this.BaseStream != null)
				{
					this.BaseStream.Dispose();
				}
			}
			finally
			{
				this.BaseStream = null;
			}
		}

		#endregion
	}
}
